
#include "tab0.h"
#include "tab2.h"

/* First is the initial call for the task
   n;p is the classical math sense

   n total number of objects
   p number of object to select (maxi is p=10)

   d in the entry table
   f is the result table  both size n
*/
 
 void COMBINE::First(int ne,int pe,USHORT * d, USHORT * f )    {
	 entry=d; 
	 output=f;   
	 p=pe;  
	 if(p>10)		 p=10;  // safety measure, not auhorised
	 lim=p-1; 
	 n=ne;
     for(UINT i=0,v=n-p;i<p;i++,v++) 		 inds[i]=v;
     Sort();
 }
 /* move step by step from p upper index to p lower index
    return 1 if ok;  0 if over
 */
 int COMBINE::Next()  {
	 if(inds[lim]==lim) 		 return 0; // finished
     int i=0; 
	 while(inds[i]==i) 
		 i++; // lock for first that can go down
	 inds[i]--; // back one for that one
	 UINT v=inds[i];  // an restart below with no hole
	 while(i--) inds[i]=--v;
	 Sort();    
	 return 1;
 }

/* send back the entry table with first p as the selection
   others after the selection
   inds is the list of "p" index selected
*/

 void COMBINE::Sort()   { 
	 UINT is=0,js=n-p,jns=0;
	 for(UINT i=0;i<n;i++) {
		 if(i-inds[is] ){
		   output[jns++]=entry[i]; 
		   continue;
		}
	    output[js++]=entry[i];
		if(is<p-1)   // don't pass the limit of the table inds
			is++;   
	 }   

 }  

  
/* tables used in symmetry processing
   [36][2] sd1_36  diagonal  sd2_36 diag 2   sst_36 stick
   sc_40[40][2] central   sr90_20[20][4] rot 90
   sym_81[5][81] direct sym   d1  d2 st cc r90
   sym_f9[3][9] fix positions  d1 d2 stick

*/

USHORT perms_band[6][3]={0,1,2,0,2,1,1,0,2,// band order
                        1,2,0,2,0,1,2,1,0};  // all perms

USHORT sh_36[36][2]={
0 , 72, 1 , 73, 2 , 74, 3 , 75,4,76,5,77,6,78,7,79,8,80,  // 9
9 , 63,10,64,11,65,12,66,13,67,14,68,15,69,16,70,17,71,  // 18
18,54,19,55,20,56,21,57,22,58,23,59,24,60,25,61,26,62, //27
27,45,28,46,29,47,30,48,31,49,32,50,33,51,34,52,35,53 // 36
};

USHORT sv_36[36][2]={  // only searched as direct
0,8, 1,7, 2,6, 3,5,  // 4
9,17, 10,16, 11,15, 12,14,  // 8
18,26, 19,25, 20,24, 21,23,  // 12
27,35, 28,34, 29,33, 30,32,  // 16
36,44, 37,43, 38,42, 39,41,  // 20
45,53, 46,52, 47,51, 48,50,  // 24
54,62, 55,61, 56,60, 57,59,  // 28
63,71, 64,70, 65,69, 66,68,  // 32
72,80, 73,79, 74,78, 75,77  // 36
};

USHORT sd1_36[36][2]={
31,39, 32,48, 41,49, // box 5
1,9, 2,18, 3,27, 4,36, 5,45, // band1 stack 1 
11,19, 12,28, 13,37, 14,46, 
21,29, 22,38, 23,47, 
6,54, 7,63, 8,72, 15,55,16,64, 17,73, 
24,56, 25,65, 26,74,  
33,57, 34,66, 35,75, 42,58, 43,67, 44,76, 
51,59, 52,68, 53,77, 61,69, 62,78, 71,79   
};
USHORT sd2_36[36][2]={ // only searched as direct
7 , 17, 6 , 26, 5 , 35, 4 , 44,  // 4
3 , 53, 2 , 62, 1 , 71, 0 , 80,  // 8
15 , 25, 14 , 34, 13 , 43, 12 , 52,  // 12
11 , 61, 10, 70, 9 , 79, 23 , 33,  // 16
22 , 42, 21 , 51, 20 , 60, 19 , 69,  // 20
18 , 78, 31 , 41, 30 , 50, 29 , 59,  // 24
28 , 68, 27 , 77, 39 , 49, 38 , 58,  // 28
37 , 67, 36 , 76, 47 , 57, 46 , 66,  // 32
45 , 75, 55 , 65, 54 , 74, 63 , 73  // 36
};
USHORT sst_36[36][2]={
27,29, 36,38, 45,47,// Box4 and stack 1
1 ,55, 10,64, 19,73 , 0,56, 2,54, 9,65, 11,63, 18,74, 20,72,
30 , 32, 39 ,  41,48 , 50, //box 5 stack 2
4,58, 13,67, 22,76, 3,59, 12,68, 21,77, 5,57, 14,66, 23,75,
33,35, 42,44, 51,53,  //box 6 stack 3
7,61, 16,70, 25,79, 6,62, 15,71, 24,80, 8,60, 17,69, 26,78
};
USHORT sc_40[40][2]={
80 , 0, 79 , 1, 78 , 2, 77 , 3,  //4
76 , 4, 75 , 5, 74 , 6, 73 , 7,  //8
72 , 8, 71 , 9, 70 , 10, 69 , 11,  //12
68 , 12, 67 , 13, 66 , 14, 65 , 15,  //16
64 , 16, 63 , 17, 62 , 18, 61 , 19,  //20
60 , 20, 59 , 21, 58 , 22, 57 , 23,  //24
56 , 24, 55 , 25, 54 , 26, 53 , 27,  //28
52 , 28, 51 , 29, 50 , 30, 49 , 31,  //32
48 , 32, 47 , 33, 46 , 34, 45 , 35,  //36
44 , 36, 43 , 37, 42 , 38, 41 , 39  //40
};
USHORT sr90_20[20][4]={
0 , 8, 80 , 72, 1 , 17, 79 , 63, 2 , 26, 78 , 54, 3 , 35, 77 , 45,  // 4
4 , 44, 76 , 36, 9 , 7, 71 , 73, 10 , 16, 70 , 64, 11 , 25, 69 , 55,  // 8
12 , 34, 68 , 46, 13 , 43, 67 , 37, 18 , 6, 62 , 74, 19 , 15, 61 , 65,  // 12
20 , 24, 60 , 56, 21 , 33, 59 , 47, 22 , 42, 58 , 38, 27 , 5, 53 , 75,  // 16
28 , 14, 52 , 66, 29 , 23, 51 , 57, 30 , 32, 50 , 48, 31 , 41, 49 , 39  // 20
};
USHORT sym_81[5][81]={    // d1  d2  st  c  r90
0 , 9 , 18 , 27 , 36 , 45 , 54 , 63 , 72 , 1 , 10 , 19 , 28 , 37 , 46 , 55 , 64 , 73 , 2 , 11 , 
20 , 29 , 38 , 47 , 56 , 65 , 74 , 3 , 12 , 21 , 30 , 39 , 48 , 57 , 66 , 75 , 4 , 13 , 22 , 31 , 
40 , 49 , 58 , 67 , 76 , 5 , 14 , 23 , 32 , 41 , 50 , 59 , 68 , 77 , 6 , 15 , 24 , 33 , 42 , 51 , 
60 , 69 , 78 , 7 , 16 , 25 , 34 , 43 , 52 , 61 , 70 , 79 , 8 , 17 , 26 , 35 , 44 , 53 , 62 , 71 , 80 ,  // d1
80 , 71 , 62 , 53 , 44 , 35 , 26 , 17 , 8 , 79 , 70 , 61 , 52 , 43 , 34 , 25 , 16 , 7 , 78 , 69 , 
60 , 51 , 42 , 33 , 24 , 15 , 6 , 77 , 68 , 59 , 50 , 41 , 32 , 23 , 14 , 5 , 76 , 67 , 58 , 49 , 
40 , 31 , 22 , 13 , 4 , 75 , 66 , 57 , 48 , 39 , 30 , 21 , 12 , 3 , 74 , 65 , 56 , 47 , 38 , 29 , 
20 , 11 , 2 , 73 , 64 , 55 , 46 , 37 , 28 , 19 , 10 , 1 , 72 , 63 , 54 , 45 , 36 , 27 , 18 , 9 , 0 ,  // d2
56 , 55 , 54 , 59 , 58 , 57 , 62 , 61 , 60 , 65 , 64 , 63 , 68 , 67 , 66 , 71 , 70 , 69 , 74 , 73 , 
72 , 77 , 76 , 75 , 80 , 79 , 78 , 29 , 28 , 27 , 32 , 31 , 30 , 35 , 34 , 33 , 38 , 37 , 36 , 41 , 
40 , 39 , 44 , 43 , 42 , 47 , 46 , 45 , 50 , 49 , 48 , 53 , 52 , 51 , 2 , 1 , 0 , 5 , 4 , 3 , 
8 , 7 , 6 , 11 , 10 , 9 , 14 , 13 , 12 , 17 , 16 , 15 , 20 , 19 , 18 , 23 , 22 , 21 , 26 , 25 , 24 ,  //st
80 , 79 , 78 , 77 , 76 , 75 , 74 , 73 , 72 , 71 , 70 , 69 , 68 , 67 , 66 , 65 , 64 , 63 , 62 , 61 , 
60 , 59 , 58 , 57 , 56 , 55 , 54 , 53 , 52 , 51 , 50 , 49 , 48 , 47 , 46 , 45 , 44 , 43 , 42 , 41 , 
40 , 39 , 38 , 37 , 36 , 35 , 34 , 33 , 32 , 31 , 30 , 29 , 28 , 27 , 26 , 25 , 24 , 23 , 22 , 21 , 
20 , 19 , 18 , 17 , 16 , 15 , 14 , 13 , 12 , 11 , 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 ,  // c
8 , 17 , 26 , 35 , 44 , 53 , 62 , 71 , 80 , 7 , 16 , 25 , 34 , 43 , 52 , 61 , 70 , 79 , 6 , 15 , 
24 , 33 , 42 , 51 , 60 , 69 , 78 , 5 , 14 , 23 , 32 , 41 , 50 , 59 , 68 , 77 , 4 , 13 , 22 , 31 , 
40 , 49 , 58 , 67 , 76 , 3 , 12 , 21 , 30 , 39 , 48 , 57 , 66 , 75 , 2 , 11 , 20 , 29 , 38 , 47 , 
56 , 65 , 74 , 1 , 10 , 19 , 28 , 37 , 46 , 55 , 64 , 73 , 0 , 9 , 18 , 27 , 36 , 45 , 54 , 63 , 72  }; // r90


USHORT sym_f9[3][9] ={  // d1 d2 st
0 , 10 , 20 , 30 , 40 , 50 , 60 , 70 , 80 ,  // d1
8 , 16 , 24 , 32 , 40 , 48 , 56 , 64 , 72 ,  // d2
28 , 31 , 34 , 37 , 40 , 43 , 46 , 49 , 52   // st
};

USHORT  sym_tcor[3][9]={
	0,2,1,4,3,6,5,8,7,   // central
    0,1,2,4,3,6,5,8,7,   // 3 fix
	0,2,3,4,1,6,7,8,5,   // r90
	};  



USHORT skloop_boxes_table[15][6]= // 4 boxes in square
      {{0,1,4,3,0,0},     {0,1,7,6,0,0},	     {3,4,7,6,0,0},
	  {0,2,5,3,0,0},      {0,2,8,6,0,0},	     {3,5,8,6,0,0},
	  {1,2,5,4,0,0},      {1,2,8,7,0,0},		 {4,5,8,7,0,0}, 
	      // 6 boxes
      {0,1,4,5,8,6},     {0,1,7,8,5,3},         {0,2,5,4,7,6},
      {0,2,8,7,4,3},     {1,2,5,3,6,7},         {1,2,8,6,3,4}	};

USHORT skloop_sub_table[9][4]= {// relative row,col in box
	{1,2,3,6},     {0,2,4,7},   {0,1,5,8},			// empty row1
	{4,5,0,6},	   {3,5,1,7},   {3,4,2,8},			// empty row2
	{7,8,0,3},	   {6,8,1,4},   {6,7,2,5}  };		// empty row 3
USHORT mask9_row_col [6]={0x0007,0x0038,0x01C0,
	                      0x0049,0x0092,0x0124};
USHORT cross_relative_box1[3]={0x0038,0x0007,0x0007};
USHORT cross_relative_box2[3]={0x01C0,0x01C0,0x0038};
USHORT cross_relative_outband[3]={0x0038+0x01C0,0x0007+0x01C0,0x0007+0x0038};


COMB9 tcomb9[9+36+84+126] [2];
int indtcomb9[5]={0,9,9+36,9+36+84,129+126};
USHORT indtcomb9rev[512];


class GEN_TABLES2{
public:
	GEN_TABLES2(){ 
	//============== 
	COMBINE combi; 
	USHORT  trc[9]={8,7,6,5,4,3,2,1,0},trc_s[9];
	int n=-1;
	for(int i=0;i<512;i++) indtcomb9rev[i]=0;
	for(int i=1,i2=8;i<5;i++,i2--){
		combi.First(9,i,trc,trc_s); // build the r/c lot3 tables
		while(++n ) { 
			COMB9 * tc9=tcomb9[n];
			tc9[0].bm.f=tc9[1].bm.f=0;
			for(int j=0;j<9;j++){
				if(j<i2) tc9[1].bm.Set(trc_s[j]);
				else   tc9[0].bm.Set(trc_s[j]);		// smallest in 0		
			}
			tc9[0].nt=tc9[0].bm.String(tc9[0].t);
			tc9[1].nt=tc9[1].bm.String(tc9[1].t);
			indtcomb9rev[tc9[0].bm.f]=n;
			indtcomb9rev[tc9[1].bm.f]=n+(1<<11);
			if(!combi.Next()) break; 	 
		}
		
		}
		Gen4();
	}

	void Gen4();
}gen_tables2;

USHORT mask_mini_row[3]={7,7<<3,7<<6},
	   mask_mini_col[3]={1+8+64,73<<1,73<<2},
	   mask_empty_holes[9];

void GEN_TABLES2::Gen4(){
	for(int i=0,ij=0;i<3;i++)for(int j=0;j<3;j++,ij++){
		mask_empty_holes[ij]=0x1ff ^ (mask_mini_row[i] | mask_mini_col[j]);
	}

}


//=======================



USHORT BF16::String(USHORT * r){ // same as BF32 mas 2 bytes active
	if(!f)	return 0;
	USHORT n=0,drb=0;
	word v=f;
	while(1){ // stop as soon as possible
		int mybyte=v&0xff;
		if(mybyte){
			int il=tv_strindex[mybyte];
			for(int  i=tv_strindex[mybyte-1];i<il;i++){
				r[n++]=tv_string[i]+drb;
			}
		}
		v>>=8;
		if(!v)				break;
		drb+=8;
	}
	return n;	
}

/*
const unsigned char toPos[] = {  // replaced by TblBitIndex[257] requiring non zero byte
		0,1,2,0,3,0,0,0,4,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8};
*/
BF_FIX bf_fix ={
// exocets processing trough BF8
	{0,1,  0,2,  1,2},     //tp3
	{0,1,  2,3,  0,2,  1,3,  0,3, 1,2},  // tp6
	{0x05, 0x0a, 0x09, 0x06, 0x12,  0x11, 0x21,   0x22   },	// texset
	//1.1. .1.1  1..1 .11.   .1..1  1...1 1....1 .1....1  (read right to left)
	// 0     1    2    3      4      5     6       7       (index in texset)
	{0,1, 1,0, 2,3, 3,2},     // texset4
	{0,4, 2,4, 1,5, 3,5, 4,0, 4,2, 5,1, 3,5,}, // texset 5
	{0,4, 0,6, 2,4, 2,6, 1,5, 1,7, 3,5, 3,7, 
	 4,0, 6,0, 4,2, 6,2, 5,1, 7,1, 5,3, 7,3}, //texset 6 

};

inline unsigned int popCount32(unsigned int v) { // count bits set in this (32-bit value)
	v = v - ((v >> 1) & 0x55555555);                    // reuse input as temporary
	v = (v & 0x33333333) + ((v >> 2) & 0x33333333);     // temp
	return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
}	


USHORT BF32::String(USHORT * r){
	if(!f)	return 0;
	USHORT n=0,drb=0;
	unsigned int v=f;
	while(1){ // stop as soon as possible
		int mybyte=v&0xff;
		if(mybyte){
			int il=tv_strindex[mybyte];
			for(int  i=tv_strindex[mybyte-1];i<il;i++){
				r[n++]=tv_string[i]+drb;
			}
		}
		v>>=8;
		if(!v)				break;
		drb+=8;
	}
	return n;	
}


// should be replaced by appropriate byte and dr value

USHORT BF32::String(USHORT * r,int i1,int i2){
	UINT  n=0,x=1<<i1;
	for(int i=i1;i<i2;i++){
		if(f&x) r[n++]=i;
		x=x<<1;
	}
	return n;
}

//==========================================BUILDSTRING
void BUILDSTRING::Astr(const char * x){
	if(strlen(x)<=(unsigned int)(lim-p))
		p=stpcpy(p,x);
}


void BUILDSTRING::Close(){
	if(p<zs || p>lim)	{	zs[0]=0; p=zs;}
	else	(*p)=0;
}

void BUILDSTRING::Aunit(int x){
	char *t="RCB";
	(*p++)=t[x/9];
	Achint(x%9);
}

void BUILDSTRING::AScand(SCAND x){
	if(x & (1<<11)) (*p++)='~';
	char dg= ((x>>7) & 15) +'0';
	(*p++)=dg+1;
	Astr(C_fix[x &0x7f].pt);
}

void BUILDSTRING::Store(SCAND & w){
		USHORT ws=w>>11,wd=(w>>7) & 15, wc=w & 0x7f;
		Astr(ws? " ~":" ");
		Achint(wd);
		Astr(C_fix[wc].pt);
}

void BUILDSTRING::StoreChain(SCAND * t, int n){
	for(int i=0;i<n;i++)	Store(t[i]);
	Aendl();
}



void BUILDSTRING::StoreX(SCAND & w,int dig){
		USHORT ws=w>>7, wc=w & 0x7f;
		Astr(ws? " ~":" ");
		Achint(dig);
		Astr(C_fix[wc].pt);
}

void BUILDSTRING::StoreXChain(SCAND * t, int n,int dig){
	Astr(" xchain ");
	for(int i=0;i<n;i++)	StoreX(t[i],dig);
	Aendl();
}
